package cn.wildfire.chat.app.extendsion.utils;


import android.content.Context;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.util.concurrent.TimeUnit;

import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;

/**
 * Create by HEKE, 2019/9/10 4:31
 * TODO 单线程断点续传下载文件
 */
public class SingleThreadDownader {

    public static final int TYPE_SUCCESS = 0;

    public static final int TYPE_FAILED = 1;

    public static final int MAX_COUNT = 10;// 重试的最大次数

    private DownloadReceiverInterface receiver;

    private String downloadUrl;
    private Context context;
    private String downloadedFileName;
    long contentLength;

    protected long originFilesSize;

    public SingleThreadDownader(Context _context, String _downloadUrl, String _downloadedFileName, DownloadReceiverInterface listener) {
        this.context = _context;
        this.downloadUrl = _downloadUrl;
        this.downloadedFileName = _downloadedFileName;
        this.originFilesSize = -1;
        this.receiver = listener;
    }

    public void work() {
        new Thread(new Runnable() {
            @Override
            public void run() {
                contentLength = getContentLength(downloadUrl);
                if (contentLength == 0) {
                    receiver.downloadFailed();
                    return;
                }

                if (originFilesSize == -1) {
                    originFilesSize = contentLength;
                }
                for (int i = 0; i < MAX_COUNT; i++) {
                    int x = download();

                    switch (x) {
                        case TYPE_SUCCESS:
                            receiver.downloadFinish();
                            return;
                        case TYPE_FAILED:
                            //SLEEP 3S
                            try {
                                Thread.sleep(3 * 1000);
                            } catch (InterruptedException e) {
                            }
                            continue;
                        default:
                            break;
                    }
                }
                receiver.downloadFailed();
            }
        }).start();
    }

    protected Integer download() {
        File f = new File(downloadedFileName);
        InputStream is = null;
        RandomAccessFile savedFile = null;
        long downloadLength = 0;
        if (f.exists()) {
            downloadLength = f.length();
        } else {
            try {
                f.createNewFile();
            } catch (IOException e) {
                return TYPE_FAILED;
            }
        }

        if (contentLength == downloadLength) {
            return TYPE_SUCCESS;
        }
        OkHttpClient client = new OkHttpClient.Builder().connectTimeout(900, TimeUnit.SECONDS).readTimeout(1800, TimeUnit.SECONDS).writeTimeout(900, TimeUnit.SECONDS).build();
        Request request = new Request.Builder().addHeader("RANGE", "bytes=" + downloadLength + "-" + contentLength).url(downloadUrl).build();
        try {
            Response response = client.newCall(request).execute();
            if (response != null) {
                is = response.body().byteStream();
                savedFile = new RandomAccessFile(f, "rw");
                savedFile.seek(downloadLength);
                byte[] b = new byte[1024];
                int len;
                long currentIndex = downloadLength;
                while ((len = is.read(b)) != -1) {
                    currentIndex += len;
                    savedFile.write(b, 0, len);
                    try {
                        Thread.sleep(2);
                    } catch (InterruptedException e) {
                    }
                    // 计算进度
                    if (receiver != null) {
                        float ratio = currentIndex * 1f / originFilesSize;
                        receiver.onProgress(originFilesSize, currentIndex, ratio);
                    }
                }
                response.body().close();
                if (receiver != null) {
                    receiver.onProgress(originFilesSize, 0, 0);
                }
                return TYPE_SUCCESS;
            } else {
                return TYPE_FAILED;
            }
        } catch (IOException e) {
            return TYPE_FAILED;
        } finally {
            try {
                if (is != null) {
                    is.close();
                }
                if (savedFile != null) {
                    savedFile.close();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

    }

    private long getContentLength(String downloadUrl) {
        OkHttpClient client = new OkHttpClient();
        Request request = new Request.Builder().url(downloadUrl).build();
        try {
            Response response = client.newCall(request).execute();
            if (response != null && response.isSuccessful()) {
                long contentLength = response.body().contentLength();
                response.body().close();
                return contentLength;
            }
        } catch (IOException e) {
        }
        return 0;
    }

    /**
     * Create by HEKE, 2019/9/10 4:29
     * TODO 接口回调
     */
    public interface DownloadReceiverInterface {
        void downloadFinish();

        void onProgress(long total, long progress, float ratio);

        void downloadFailed();
    }

}